package cc.linker.steplink.crm.task;

import cc.linker.steplink.crm.commons.Constants;
import cc.linker.steplink.crm.commons.RandomCodeGenerator;
import cc.linker.steplink.crm.commons.RedisConstants;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.lock.LettuceLock;
import cc.linker.steplink.crm.commons.lock.RedisLock;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.dao.SyncContentDao;
import cc.linker.steplink.crm.dao.SyncDao;
import cc.linker.steplink.crm.domain.*;
import cc.linker.steplink.crm.response.GlobalException;
import cc.linker.steplink.crm.service.ICustomerBindService;
import cc.linker.steplink.crm.support.oauth.GetOrRefreshToken;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 同步内容库用户(行为)，单次500条
 * 用户阅读文章的行为，无效用户不保存，但仍记录行为数据
 */
//@Component
@Deprecated
public class SyncContentLibraryUser {

    @Autowired
    private SyncContentDao syncContentDao;
    @Autowired
    private SyncDao syncDao;
    @Autowired
    private HttpService httpService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private GetOrRefreshToken getOrRefreshToken;
    @Autowired
    private LettuceLock lettuceLock;
    @Autowired
    private ICustomerBindService customerBindService;

    @Autowired
    private SystemProperties systemProperties;

    private final static String USER_ACTION_URL = "operation/dataList";

    private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Async
    @RedisLock("SyncContentLibraryUser")
//    @Scheduled(cron = "0 0 0 * * *")
//    @Scheduled(cron = "0/30 * * * * *")
    public void work() {
        //内容库数据
        Date date = syncContentDao.findLatestActionTime();
//        String url = "http://192.1.4.162:8082/operation/dataList";
        String contentUrl = systemProperties.getSync().getContentUrl();
        if (!contentUrl.endsWith("/")) {
            contentUrl = contentUrl + "/";
        }
        contentUrl = contentUrl + USER_ACTION_URL;
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");

        // 鉴权
        String accessToken = redisTemplate.opsForValue().get(RedisConstants.CRM_OAUTH_ACCESS_TOKEN);
        if (StringUtils.isEmpty(accessToken)) {
            getOrRefreshToken.refresh();
            accessToken = redisTemplate.opsForValue().get(RedisConstants.CRM_OAUTH_ACCESS_TOKEN);
        }
        headers.put("Authorization", "bearer " + accessToken);

        // 每次500条，当没有数据或上次小于500条时不再请求数据
        boolean hasData = true;
        while (hasData) {// 按照创建时间同步
            Map<String, Object> params = new HashMap<>();
            if (date != null) {
                params.put("createTime", format.format(date));
            } else {
                params.put("createTime", "2019-07-01 00:00:00");
            }
//        params.put("createTime", "2019-06-02 21:08:38");

            String resultJson = "";
            try {
                resultJson = httpService.doPost(contentUrl, params, headers);
            } catch (Exception e) {

            }

            if (StringUtils.isEmpty(resultJson)) {
                return;
            }
            JSONObject result = JSON.parseObject(resultJson);
            if (result == null || !"200".equals(result.getString("code"))) {
                return;
            }
            JSONArray data = result.getJSONArray("data");
            if (data == null || data.isEmpty()) {
                return;
            } else {
                if (data.size() < 500) {
                    // 每次500条，此次运行后不再请求数据
                    hasData = false;
                }
            }
            // 存储token和机构对应关系
            Map<String, String> orgIds = new HashMap<>();
            for (Object obj : data) {
                JSONObject userAndAction = (JSONObject) obj;
                JSONObject user = userAndAction.getJSONObject("user");
                JSONObject action = userAndAction.getJSONObject("action");
                if (user == null || action == null) {
                    continue;
                }
                String customerName = user.getString("weiXinUserName");
                String customerAddress = user.getString("address");
                String customerSex = user.getString("weiXinUserSex");
                String openid = user.getString("oneOpenId");
                String globalOpenid = user.getString("globalOpen_id");
                String token = user.getString("oneToken");
                String customerAvatar = user.getString("weiXinUserHeadUrl");
                String organizationNum = action.getString("organizationNum");

                //判断用户是否存在（合并其他来源）
                String customerId = "";
                // 基础信息
                Customer newCustomer = new Customer();
                newCustomer.setCreateUser("内容库");
                newCustomer.setCustomerSourceChannel(Byte.valueOf("2"));
                newCustomer.setCustomerName(StringUtils.isEmpty(customerName) ? "" : customerName);
                newCustomer.setCustomerPhone("");
                newCustomer.setCustomerAvatar(StringUtils.isEmpty(customerAvatar) ? "" : customerAvatar);
                newCustomer.setOrgId("");
                newCustomer.setAdminId("");

                // 扩展信息
                CustomerInfo customerInfo = new CustomerInfo();
                customerInfo.setCustomerInfoId(UUID.randomUUID().toString());
                customerInfo.setCustomerAddress(customerAddress == null ? "" : customerAddress);
                customerInfo.setCustomerCompany("");
                customerInfo.setCustomerFax("");
                customerInfo.setCustomerArea("");

                String orgId = "";
                // 若没提供机构码
                if (StringUtils.isEmpty(orgId) && !StringUtils.isEmpty(token)) {
                    if (orgIds.containsKey(token)) {
                        orgId = orgIds.get(token);
                    } else {
                        orgId = getOrgCodeByToken(token);
                        orgIds.put(token, orgId);
                    }
                }
                if (!StringUtils.isEmpty(openid) && !StringUtils.isEmpty(token)) {
                    //根据openid, token判断用户是否存在，只有globalOpenid的无法确定具体公众号下的用户，不存
                    Customer oneCustomer = syncContentDao.findCustomerByOpenidAndToken(openid, token);
                    String lockKey = "SyncContentLibraryUser" + openid + token;
                    String requestId = UUID.randomUUID().toString();
                    boolean lock = lettuceLock.tryLock(lockKey,requestId,1, TimeUnit.MINUTES);
                    if (!lock) {
                        continue;
                    }
                    try{
                        if (oneCustomer != null) {
                            customerId = oneCustomer.getCustomerId();
                            // 获取机构码
                            if (StringUtils.isEmpty(oneCustomer.getOrgId())) {
                                oneCustomer.setOrgId(orgId);
                            } else {
                                if (StringUtils.isEmpty(orgId)) {
                                    orgId = oneCustomer.getOrgId();
                                }
                            }
                            oneCustomer.setCustomerName(newCustomer.getCustomerName());
                            oneCustomer.setCustomerAvatar(newCustomer.getCustomerAvatar());
                            try {
                                // 尝试更新用户
                                syncContentDao.updateCustomerSetGlobalOpenid(oneCustomer);
                            } catch (Exception e) {
                                // 忽略更新失败
                            }
                        } else {
                            // 用户不存在，保存用户
                            customerId = RandomCodeGenerator.getCustomerId(Constants.CUSTOMER_CODE_SOURCE_CONTENT);
                            newCustomer.setCustomerId(customerId);
                            newCustomer.setWxToken(token);
                            newCustomer.setWxOpenid(openid);
                            newCustomer.setWxGlobalOpenid(globalOpenid);
                            newCustomer.setAdminId("内容库");
                            newCustomer.setCreateUser("内容库");
                            // 设置机构码
                            newCustomer.setOrgId(orgId);

                            syncDao.addCustomer(newCustomer);

                            customerInfo.setCustomerId(customerId);
                            syncDao.addCustomerInfo(customerInfo);
                        }
                    } finally {
                        // 解锁
                        lettuceLock.releaseLock(lockKey,requestId);
                    }
                }

                // 保存用户行为记录
                Integer userOperate = action.getInteger("userOperate");
                String createTime = action.getString("createTime");
                Date actionTime = null;
                try {
                    actionTime = format.parse(createTime);
                    if (date == null) {
                        date = actionTime;
                    } else {
                        if (date.before(actionTime)) {
                            date = actionTime;
                        }
                    }
                } catch (ParseException e) {

                }

                Integer readTimeSum = action.getInteger("readTimeSum");
                String newsClassificationId = action.getString("newsClassificationId");
                String newsLabel = action.getString("newsLabel");
                String newsId = action.getString("newsId");
                String userOperateDescribe = action.getString("userOperateDescribe");

                ActionContent actionContent = new ActionContent();
                // customerId可能没有，过滤了用户但行为同步以备后面根据globalOpenid更新
                actionContent.setCustomerId(customerId);
                actionContent.setActionContentId(UUID.randomUUID().toString());
                actionContent.setActionType(userOperate);
                actionContent.setActionTime(actionTime);
                actionContent.setArticleId(newsId);
                actionContent.setArticleLabels(newsLabel);
                actionContent.setArticleTypes(newsClassificationId);
                actionContent.setArticleReadTime(readTimeSum == null ? 0 : readTimeSum);
                actionContent.setActionRemark(userOperateDescribe);
                actionContent.setWxGlobalOpenid(globalOpenid);
                actionContent.setWxOpenid(openid);
                actionContent.setWxToken(token);
                actionContent.setOrgId(orgId);

                syncContentDao.addContentUserAction(actionContent);

            }
        }

    }

    private String getOrgCode(Customer oneCustomer, String token) {
        if (oneCustomer != null) {
            if (StringUtils.isEmpty(oneCustomer.getOrgId())) {
                String orgCode = getOrgCodeByToken(token);
                oneCustomer.setOrgId(orgCode);
                return orgCode;
            } else {
                return oneCustomer.getOrgId();
            }
        } else {
            return getOrgCodeByToken(token);
        }
    }

    private String getOrgCodeByToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return "";
        }
        try {
            WxOrgInfo wxOrgInfo = customerBindService.getOrgInfo(
                    new BindUserDto(null, null, null, null, token, null), true);
            String orgCode = wxOrgInfo != null ? wxOrgInfo.getOrgcode() : "";
            return orgCode;
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
        }
        return "";
    }
}

